import roomMgr from './roommgr';
import userMgr from './usermgr';
import mjutils from './mjutils';
import db from '../utils/db';
import crypto from '../utils/crypto';


const games: {[key: string]: game} = {};
const gameSeatsOfUsers: {[key: string]: gameSeat} = {};

export  default  class Gamemgr_xlch{
    
    static setReady(userId, callback?){

        const roomId = roomMgr.getUserRoom(userId);
        if(roomId == null){
            return;
        }

        const roomInfo = roomMgr.getRoom(roomId);
        if(roomInfo == null){
            return;
        }

        roomMgr.setReady(userId, true);

        const game = games[roomId];
        if(game == null){
            if(roomInfo.seats.length == 4){
                for(let i = 0; i < roomInfo.seats.length; i++){
                    const s = roomInfo.seats[i];
                    if(s.ready == false || userMgr.isOnline(s.userId) == false){
                        return;
                    }
                }
                //4个人都到齐了并且都准备了，则开始新的一局
                this.begin(roomId);
            }
        }
        else{
            let numOfMJ = game.mahjongs.length - game.currentIndex;
            let remainingGames = roomInfo.conf.maxGames - roomInfo.numOfGames;

            let data: game = {
                state: game.state,
                numOfmj: numOfMJ,
                button: game.button,
                turn: game.turn,
                chuPai: game.chuPai,
            };
            data.seats = <gameSeat[] & { [key: string]: gameSeat }>[];
            let seatData: gameSeat = null;
            for(let i = 0; i < 4; i++){
                let sd = game.gameSeats[i];
                let s: gameSeat = {
                    userId: sd.userId,
                    folds: sd.folds,
                    angangs: sd.angangs,
                    diangangs: sd.diangangs,
                    wangangs: sd.wangangs,
                    pengs: sd.pengs,
                    que: sd.que,
                    hued: sd.hued,
                    huInfo: sd.huInfo,
                    iszimo: sd.iszimo,
                };
                if(sd.userId == userId){
                    s.holds = sd.holds;
                    s.huanpais = sd.huanpais;
                    seatData = sd;
                }
                else{
                    s.huanpais = sd.huanpais ? [] : null;
                }
                data.seats.push(s);
            }
            //同步整个信息给客户端
            userMgr.sendMsg(userId, 'game_sync_push', data);
            sendOperations(game, seatData, game.chuPai);
        }
    }

    /**
     * 开始新的一局
     * @param roomId 
     */
    static begin(roomId){

        const roomInfo = roomMgr.getRoom(roomId);
        if(roomInfo == null){
            return;
        }

        const seats = roomInfo.seats;
        const game: game = {
            conf: roomInfo.conf,
            roomInfo: roomInfo,
            gameIndex: roomInfo.numOfGames,
            button: roomInfo.nextButton,
            mahjongs: new Array(108),
            currentIndex: 0,
            gameSeats: <gameSeat[] & { [key: string]: gameSeat }>new Array(4),
            numOfQue: 0,
            turn: 0,
            chuPai: -1,
            state: 'idle',
            firstHupai: -1,
            yipaoduoxiang: -1,
            fangpaoshumu: -1,
            actionList: [],
            chupaiCnt: 0,
        };

        roomInfo.numOfGames++;

        for(let i = 0; i < 4; i++){
            const data = game.gameSeats[i] = <gameSeat>{};
            data.game = game;
            data.seatIndex = i;
            data.userId = seats[i].userId;
            data.holds = [];
            data.folds = [];
            data.angangs = [];
            data.diangangs = [];
            data.wangangs = [];
            data.pengs = [];
            data.que = -1;
            data.huanpais = null;
            data.countMap = {};
            data.tingMap = {};
            data.pattern = '';
            data.canGang = false;
            data.gangpai = [];
            data.canPeng = false;
            data.canHu = false;
            data.canChuPai = false;
            data.guoHuFan = -1;
            data.hued = false;
            data.actions = [];
            data.iszimo = false;
            data.isGangHu = false;
            data.fan = 0;
            data.score = 0;
            data.huInfo = [];
            data.lastFangGangSeat = -1;
            data.numZiMo = 0;
            data.numJiePao = 0;
            data.numDianPao = 0;
            data.numAnGang = 0;
            data.numMingGang = 0;
            data.numChaJiao = 0;
            gameSeatsOfUsers[data.userId] = data;
        }
        games[roomId] = game;

        shuffle(game);
        deal(game);

        const numOfMJ = game.mahjongs.length - game.currentIndex;
        const huansanzhang = roomInfo.conf.hsz;

        for(let i = 0; i < seats.length; i++){
            const s = seats[i];
            //通知玩家手牌
            userMgr.sendMsg(s.userId, 'game_holds_push', game.gameSeats[i].holds);
            //通知还剩多少张牌
            userMgr.sendMsg(s.userId, 'mj_count_push', numOfMJ);
            //通知还剩多少局
            userMgr.sendMsg(s.userId, 'game_num_push', roomInfo.numOfGames);
            //通知游戏开始
            userMgr.sendMsg(s.userId, 'game_begin_push', game.button);

            if(huansanzhang == true){
                game.state = 'huanpai';
                //通知准备换牌
                userMgr.sendMsg(s.userId, 'game_huanpai_push');
            }
            else{
                game.state = 'dingque';
                //通知准备定缺
                userMgr.sendMsg(s.userId, 'game_dingque_push');
            }
        }
    }
    
}

/**
 * 检查牌里是否有能杠或能碰或能胡的牌
 * @param seatData 
 */
function hasOperations(seatData: gameSeat){
    if(seatData.canGang || seatData.canPeng || seatData.canHu){
        return true;
    }
    return false;
}

/**
 * 执行下一步操作
 * @param game 
 * @param seatData 
 * @param pai 
 */
function sendOperations(game: game, seatData: gameSeat, pai){
    if(hasOperations(seatData)){
        if(pai == -1){
            pai = seatData.holds[seatData.holds.length - 1];
        }

        let data: actionState = {
            pai: pai,
            hu: seatData.canHu,
            peng: seatData.canPeng,
            gang: seatData.canGang,
            gangpai: seatData.gangpai,
        };

        userMgr.sendMsg(seatData.userId, 'game_action_push', data);
    }
    else{
        userMgr.sendMsg(seatData.userId, 'game_action_push');
    }
}

/**
 * 洗牌
 * @param game 
 */
function shuffle(game: game){

    const mahjongs = game.mahjongs;

    // 筒 0-8表示筒子
    let index = 0;
    for(let i = 0; i < 9; i++){
        for(let c = 0; c < 4; c++){
            mahjongs[index] = i;
            index++;
        }
    }
    // 条 9-17表示条子
    for(let i = 9; i < 18; i++){
        for(let c = 0; c < 4; c++){
            mahjongs[index] = i;
            index++;
        }
    }
    // 万 18-26表示万
    for(let i = 18; i < 27; i++){
        for(let c = 0; c < 4; c++){
            mahjongs[index] = i;
            index++;
        }
    }

    // 洗牌
    for(let i = 0, l = mahjongs.length; i < l; i++){
        let lastIndex = l - 1 - i;
        let index = Math.floor(Math.random() * lastIndex);
        mahjongs[index] ^= mahjongs[lastIndex];
        mahjongs[lastIndex] ^= mahjongs[index];
        mahjongs[index] ^= mahjongs[lastIndex];
    }
}


/**
 * 发牌
 */
function deal(game: game){

    //强制清0
    game.currentIndex = 0;

    //没人13张， 一共13 * 4 = 52张 庄家多发一张共53张
    let seatIndex = game.button;
    for(let i = 0; i < 52; i++){
        let mahjongs = game.gameSeats[seatIndex].holds;
        if(mahjongs == null){
            mahjongs = [];
            game.gameSeats[seatIndex].holds = mahjongs;
        }
        mopai(game, seatIndex);
        seatIndex++;
        seatIndex %= 4;
    }

    //庄家多模最后一张牌
    mopai(game, game.button);
    //当前轮设置为庄家
    game.turn = game.button;
}


function mopai(game: game, seatIndex){

    if(game.currentIndex == game.mahjongs.length){
        return -1;
    }

    const data = game.gameSeats[seatIndex];
    const mahjongs = data.holds;
    const pai = game.mahjongs[game.currentIndex];
    mahjongs.push(pai);

    //统计牌的数目，用于快速判定
    let c = data.countMap[pai];
    if(c == null){
        c = 0;
    }
    data.countMap[pai] = c + 1;
    game.currentIndex++;
    return pai;
}